﻿using CommonBehaviors.Actions;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media;
using Action = Styx.TreeSharp.Action;

using P = Priest.PriestSettings;
using PD = Priest.PriestSettingsDisc;
using HKM = Priest.PriestHotkeyManagers;
using Styx.CommonBot.Coroutines;
using Buddy.Coroutines;

namespace Priest
{
    public partial class PriestMain : CombatRoutine
    {
        public static async Task<bool> rotationSelector()
        {
            if (MeIsShadow && await ShadowCoroutine()) return true;
            if (MeIsDisc && await DiscCoroutine()) return true;
            if (MeIsHoly && await HolyCoroutine()) return true;
            if (MeIsLowbie && await LowbieCoroutine()) return true;
            return false;
        }
        public static async Task<bool> ShadowCoroutine()
        {
            if (!AutoBot && Me.Mounted && !buffExists(TELAARI_TALBUK_INT, Me)) return false;
            if (pullTimer.IsRunning) { pullTimer.Stop(); }
            if (Me.IsCasting || Me.IsChanneling) { return false; }
            if (await CastBuff(SHADOWFORM, !Me.HasAura(SHADOWFORM) && Me.HealthPercent > P.myPrefs.PercentFlashHealCombat + 20)) return true;
            if (await MoveBack(Me.CurrentTarget != null && AllowMovement && debuffExists(VOID_TENDRILS, Me.CurrentTarget) && Me.CurrentTarget.Distance <= 9)) return true;
            if (await StopMovement(AutoBot && Me.MovementInfo.MovingBackward && DateTime.Now >= moveBackTimer)) return true;
            if (await CastBuff(PWS, !spellOnCooldown(PWS) && Me.HealthPercent <= P.myPrefs.PercentPowerWordShield && Canbuff)) return true;
            if (await CastBuff(PWF, !Me.HasAura(PWF))) return true;
            if (await CastBuff(GIFT_OF_THE_NAARU, Me.HealthPercent <= P.myPrefs.PercentNaaru && !spellOnCooldown(GIFT_OF_THE_NAARU))) return true;
            if (await CastBuff(FLASH_HEAL, Me.HealthPercent <= P.myPrefs.PercentFlashHealCombat && Canbuff)) return true;
            if (await findTargets(Me.CurrentTarget == null && AllowTargeting && FindTargetsCount >= 1)) return true;
            if (await clearTarget(Me.CurrentTarget != null && AllowTargeting && (Me.CurrentTarget.IsDead || Me.CurrentTarget.IsFriendly) && !Me.CurrentTarget.Lootable)) return true;
            if (await findMeleeAttackers(Me.CurrentTarget != null && AutoBot && AllowTargeting && Me.CurrentTarget.Distance > 10 && MeleeAttackersCount >= 1)) return true;
            if (await MoveToTarget(Me.CurrentTarget != null && AllowMovement && Me.CurrentTarget.Distance > 39f && Me.Level >= 10)) return true;
            if (await StopMovement(Me.CurrentTarget != null && AllowMovement && Me.CurrentTarget.Distance <= 39f && Me.Level >= 10 && Me.IsMoving)) return true;
            if (await MoveToTarget(Me.CurrentTarget != null && AllowMovement && Me.CurrentTarget.Distance > 29f && Me.Level < 10)) return true;
            if (await StopMovement(Me.CurrentTarget != null && AllowMovement && Me.CurrentTarget.Distance <= 29f && Me.Level < 10 && Me.IsMoving)) return true;
            if (await FaceMyTarget(Me.CurrentTarget != null && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget))) return true;

            if (await Cast(SILENCE, gotTarget
                && Me.CurrentTarget.IsCasting
                && Me.CanInterruptCurrentSpellCast
                && Me.CurrentTarget.Distance <= 30)) return true;
            if (await Cast(VOID_TENDRILS, gotTarget && addCountMelee >= P.myPrefs.VoidTendrilAdds && !spellOnCooldown(VOID_TENDRILS))) return true;
            if (await Cast(PSYCHIC_SCREAM, gotTarget && addCountMelee >= P.myPrefs.PsychicScreamAdds && !spellOnCooldown(PSYCHIC_SCREAM))) return true;
            if (await CastHeal(DISPEL_MAGIC, dispelTargets != null && !spellOnCooldown(DISPEL_MAGIC), dispelTargets)) return true;
            if (await CastBuff(DISPERSION, Me.HealthPercent <= P.myPrefs.PercentDispersion && !spellOnCooldown(DISPERSION))) return true;
            if (await CastBuff(DESPERATE_PRAYER, Me.HealthPercent <= P.myPrefs.PercentDesperatePrayer && !spellOnCooldown(DESPERATE_PRAYER))) return true;

            if (await CastBuff(POWER_INFUSION, gotTarget && !spellOnCooldown(POWER_INFUSION) && ((Targets.IsWoWBoss(Me.CurrentTarget) && AutoBot) || HKM.cooldownsOn))) return true;
            if (await Cast(SILENCE, gotTarget && SilenceConditions(Me.CurrentTarget) && Me.CurrentTarget.Distance <= 30 && interruptTimer <= DateTime.Now)) return true;
            if (await Cast(VAMPIRIC_EMBRACE, gotTarget && Me.HealthPercent <= P.myPrefs.PercentVampiricEmbrace && !spellOnCooldown(VAMPIRIC_EMBRACE))) return true;
            if (await NeedTrinket1(UseTrinket1 && nextTrinketTimeAllowed <= DateTime.Now && !P.myPrefs.Trinket1Use)) return true;
            if (await NeedTrinket2(UseTrinket2 && nextTrinketTimeAllowed <= DateTime.Now && !P.myPrefs.Trinket2Use)) return true;
            if (await CastGroundSpellTrinket(1, gotTarget && P.myPrefs.Trinket1Use && nextTrinketTimeAllowed <= DateTime.Now)) return true;
            if (await CastGroundSpellTrinket(2, gotTarget && P.myPrefs.Trinket2Use && nextTrinketTimeAllowed <= DateTime.Now)) return true;
            if (await Cast(HALO, gotTarget && addCountRange >= P.myPrefs.HaloAdds && !spellOnCooldown(HALO) && !HKM.aoeStop)) return true;
            if (await Cast(CASCADE, gotTarget && addCountRange >= P.myPrefs.CascadeAdds && !spellOnCooldown(CASCADE) && !HKM.aoeStop)) return true;
            if (await Cast(DIVINE_STAR, gotTarget && addCountRange >= P.myPrefs.DivineStarAdds && !spellOnCooldown(DIVINE_STAR) && !HKM.aoeStop)) return true;
            if (await Cast(MIND_SEAR, gotTarget
                && !Me.IsChanneling
                && IsInRange(Me.CurrentTarget)
                && addCountRange >= P.myPrefs.MindSearAdds
                && SpellManager.HasSpell(MIND_SEAR)
                && !HKM.aoeStop)) return true;
            if (await Cast(SMITE, gotTarget && Me.Level < 10 && Me.CurrentTarget.Distance <= 30)) return true;
            if (await Cast(VOID_ENTROPY, gotTarget && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && IsInRange(Me.CurrentTarget))) return true;
            if (await Cast(DEVOURING_PLAGUE, gotTarget && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3) && IsInRange(Me.CurrentTarget)) return true;

            if (await Cast(MIND_BLAST, gotTarget && !spellOnCooldown(MIND_BLAST) && IsInRange(Me.CurrentTarget))) return true;
            if (await Cast(SWD, gotTarget && !spellOnCooldown(SWD) && Me.CurrentTarget.HealthPercent < 20 && IsInRange(Me.CurrentTarget))) return true;
            if (await Cast(SMITE, gotTarget && buffExists(INSANITY_INT, Me) && IsInRange(Me.CurrentTarget))) return true;
            if (await Cast(MIND_SPIKE, gotTarget && (buffExists(TWIST_OF_FATE_INT, Me) || IsOverlayed(MIND_SPIKE_INT)))) return true;
            if (await Cast(Fiend, gotTarget && FiendConditions)) return true;
            if (await CastMultiDot(SWP, multiDotTargetsSWP, multiDotTargetsSWP != null && swpConditions(multiDotTargetsSWP) && IsInRange(Me.CurrentTarget))) return true;
            if (await CastMultiDot(VAMPIRIC_TOUCH, multiDotTargetsVT, multiDotTargetsVT != null && vtConditions(multiDotTargetsVT) && IsInRange(Me.CurrentTarget))) return true;
            if (await Cast(MIND_FLAY, gotTarget
                && !Me.IsChanneling
                && IsInRange(Me.CurrentTarget)
                && (addCountRange < P.myPrefs.MindSearAdds || !SpellManager.HasSpell(MIND_SEAR) || HKM.aoeStop))) return true;

            if (await CannotContinueFight(Me.CurrentTarget, Me.CurrentTarget != null
                && AutoBot
                && Me.CurrentTarget.HealthPercent >= 95
                && !Me.CurrentTarget.IsPlayer
                && lastGuid == Me.CurrentTarget.Guid
                && fightTimer.ElapsedMilliseconds >= 30 * 1000)) return true;


            return false;
        }

        public static async Task<bool> DiscCoroutine()
        {
            if (!AutoBot && Me.Mounted) return false;
            if (Me.IsCasting || Me.IsChanneling) return false;
            if (await findTargets(Me.CurrentTarget == null && AllowTargeting && FindTargetsCount >= 1)) return true;
            if (await clearTarget(Me.CurrentTarget != null && AutoBot && (Me.CurrentTarget.IsDead || Me.CurrentTarget.IsFriendly))) return true;
            if (await findMeleeAttackers(gotTarget && AllowTargeting && Me.CurrentTarget.Distance > 10 && MeleeAttackersCount >= 1)) return true;
            if (await FaceMyTarget(gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget) && Me.CurrentTarget.Distance <= 29f)) return true;
            if (await MoveToTarget(Me.CurrentTarget != null && AllowMovement && Me.CurrentTarget.Distance > 29f)) return true;
            if (await StopMovement(Me.CurrentTarget != null && AllowMovement && Me.CurrentTarget.Distance <= 29f && Me.IsMoving)) return true;
            //dispel purify
            if (await CastHeal(DISPEL_MAGIC, PD.myPrefs.AutoDispel && dispelTargets != null, dispelTargets)) return true;
            if (await CastHeal(PURIFY, PD.myPrefs.AutoPurify && purifyPlayers != null, purifyPlayers)) return true;


            if (await CastNonTargetSpell(ARCHANGEL, needArchangel())) return true;
            if (await CastHeal(DESPERATE_PRAYER, Me.HealthPercent <= PD.myPrefs.DesperatePrayerPercent && !spellOnCooldown(DESPERATE_PRAYER), Me)) return true;
            if (await CastHeal(GIFT_OF_THE_NAARU, Me.HealthPercent <= PD.myPrefs.GiftOfTheNaaruPercent && !spellOnCooldown(GIFT_OF_THE_NAARU), Me)) return true;
            if (await CastDmgSpell(MINDBENDER, needManaRegen && manaregenTarget != null, manaregenTarget)) return true;
            if (await CastDmgSpell(SHADOWFIEND, CanCastShadowFiend() && dpsTarget != null, dpsTarget)) return true;
            if (await CastDmgSpell(POWER_WORD_SOLACE, CanCastPowerWordSolace() && dpsTarget != null && canAttackTarget(), dpsTarget)) return true;
            if (await CastHeal(PAIN_SUPPRESSION, needPainSuppression && _painsuppressionplayer != null, _painsuppressionplayer)) return true;
            if (await CastHeal(PWS, _pwsPlayerDisc != null, _pwsPlayerDisc)) return true;
            if (await CastHeal(CASCADE, needCascade() && _cascadeplayer != null, _cascadeplayer)) return true;
            if (await CastHeal(PENANCE, _penanceDiscPlayer != null, _penanceDiscPlayer)) return true;
            if (await CastHeal(FLASH_HEAL, _flashHealDiscPlayer != null, _flashHealDiscPlayer)) return true;
            if (await CastHeal(PRAYER_OF_MENDING, _prayerOfMendingDiscPlayer != null, _prayerOfMendingDiscPlayer)) return true;
            if (await CastHeal(PRAYER_OF_HEALING, _prayerOfHealingPlayerDisc != null, _prayerOfHealingPlayerDisc)) return true;
            if (await CastHeal(HEAL, _healDiscPlayer != null, _healDiscPlayer)) return true;
            if (await CastGroundSpell(POWER_WORD_BARRIER, _powerWordBarrierPlayerDisc != null, _powerWordBarrierPlayerDisc)) return true;
            if (await CastBuff(HOLY_NOVA, needHolyNova)) return true;

            if (await CastDmgSpell(PENANCE, CanCastPenance() && dpsTarget != null && canAttackTarget(), dpsTarget)) return true;
            if (await CastDmgSpell(HOLY_FIRE, CanCastHolyFire() && dpsTarget != null && canAttackTarget(), dpsTarget)) return true;
            if (await CastDmgSpell(SMITE, CanCastSmite() && dpsTarget != null && canAttackTarget(), dpsTarget)) return true;

            //dmg not in party
            if (await CastDmgSpell(MIND_SEAR, partyCount == 0 && Me.CurrentTarget != null && addCountRange >= 5, Me.CurrentTarget)) return true;
            if (await CastDmgSpell(PENANCE, partyCount == 0 && Me.CurrentTarget != null, Me.CurrentTarget)) return true;
            if (await CastDmgSpell(SWP, partyCount == 0 && Me.CurrentTarget != null && !buffExists(SWP, Me.CurrentTarget), Me.CurrentTarget)) return true;
            if (await CastDmgSpell(HOLY_FIRE, partyCount == 0 && Me.CurrentTarget != null, Me.CurrentTarget)) return true;
            if (await CastDmgSpell(SMITE, partyCount == 0 && Me.CurrentTarget != null, Me.CurrentTarget)) return true;


            return false;
        }

        #region lowbie
        public static async Task<bool> LowbieCoroutine()
        {
            if (!AutoBot && Me.Mounted) return false;
            if (await findTargets(Me.CurrentTarget == null && AllowTargeting && FindTargetsCount >= 1)) return true;
            if (await clearTarget(Me.CurrentTarget != null && AutoBot && Me.CurrentTarget.IsDead || Me.CurrentTarget.IsFriendly)) return true;
            if (await findMeleeAttackers(gotTarget && AutoBot && AllowTargeting && Me.CurrentTarget.Distance > 10 && MeleeAttackersCount >= 1)) return true;
            if (await MoveToTarget(gotTarget && AllowMovement && Me.CurrentTarget.Distance > 30)) return true;
            if (await StopMovement(gotTarget && AllowMovement && Me.CurrentTarget.Distance <= 30)) return true;
            if (await FaceMyTarget(gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget))) return true;

            if (await Cast(SWP, gotTarget
                && !debuffExists(SWP, Me.CurrentTarget)
                || (debuffExists(SWP, Me.CurrentTarget) && debuffTimeLeft(SWP, Me.CurrentTarget) <= 4500)
                && IsInRange(Me.CurrentTarget))) return true;
            if (await Cast(SMITE, gotTarget && Me.CurrentTarget.Distance <= 30)) return true;
            return false;
        }
        #endregion

        #region holy routine
        public static DateTime refreshTimer;
        public static async Task<bool> HolyCoroutine()
        {
            if (!AutoBot && Me.Mounted && !buffExists(TELAARI_TALBUK_INT, Me)) return false;
            //movement
            if (await MoveToTarget(gotTarget && AllowMovement && Me.CurrentTarget.Distance > 39f && Me.Level >= 10)) return true;
            if (await StopMovement(gotTarget && AllowMovement && Me.CurrentTarget.Distance <= 39f && Me.Level >= 10)) return true;
            if (await FaceMyTarget(gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget))) return true;

            //free prayer of mending
            if (await CastHeal(PRAYER_OF_MENDING, needFreePrayerOfMending && canCast && _freePrayerTarget != null, _freePrayerTarget)) return true;

            //dispel purify
            if (await CastHeal(DISPEL_MAGIC, P.myPrefs.AutoHolyDispel && dispelTargets != null, dispelTargets)) return true;
            if (await CastHeal(PURIFY, P.myPrefs.AutoHolyPurify && purifyPlayers != null, purifyPlayers)) return true;
            //mana regen
            if (await CastDmgSpell(POWER_WORD_SOLACE, CanCastPowerWordSolace() && needPowerWordSolace, dpsTarget)) return true;

            //Special healing
            if (await CastHeal(FLASH_HEAL, canCast && _urgentHealPlayer != null, _urgentHealPlayer)) return true;
            if (await CastHeal(PWS, _tankPlayer != null && !buffExists(6788, _tankPlayer), _tankPlayer)) return true;
            if (await CastHeal(RENEW, needRenewOnTank && _tankRenewPlayer != null, _tankRenewPlayer)) return true;
            if (await CastHeal(GUARDIAN_SPIRIT, _guardianSpiritPlayer != null && P.myPrefs.AutoGuardianOnTank, _guardianSpiritPlayer)) return true;
            if (await CastHeal(HOLY_WORD_SERENITY, _serenityPlayer != null && buffExists(CHACKRA_SERENITY, Me), _serenityPlayer)) return true;

            //Aoe Healing
            if (await CastGroundSpell(LIGHTWELL, _lightWellPlayer != null, _lightWellPlayer)) return true;
            if (await CastHeal(CASCADE, _cascadePlayer != null, _cascadePlayer)) return true;
            if (await CastHeal(DIVINE_HYMN, _divinePlayer != null, _divinePlayer)) return true;
            if (await CastHeal(PRAYER_OF_HEALING, _prayerPlayer != null, _prayerPlayer)) return true;
            if (await CastHeal(CIRCLE_OF_HEALING, _circlePlayer != null, _circlePlayer)) return true;
            if (await CastGroundSpell(HOLY_WORD_SANCTUARY, _sanctuaryPlayer != null && buffExists(CHACKRA_SANCTUARY, Me), _sanctuaryPlayer)) return true;

            //Single healing
            if (await CastHeal(FLASH_HEAL, _flashHealPlayer != null, _flashHealPlayer)) return true;
            if (await CastHeal(HEAL, _healPlayer != null, _healPlayer)) return true;
            if (await CastMultiDot(RENEW, needRenew)) return true;
            if (await CastHeal(BINDING_HEAL, Me.HealthPercent <= BindingHealHealth && _bindingHealTarget != null && canCast, _bindingHealTarget)) return true;

            //dmg spells
            if (await CastDmgSpell(MINDBENDER, needMindbender && canCast, _mindbenderUnit)) return true;
            if (await CastDmgSpell(SWP, gotTarget && !debuffExists(SWP, Me.CurrentTarget) && MeNotInGroup && canCast, Me.CurrentTarget)) return true;
            if (await CastDmgSpell("Holy Fire", gotTarget && !spellOnCooldown("Holy Fire") && MeNotInGroup && canCast, Me.CurrentTarget)) return true;
            if (await CastDmgSpell(SMITE, gotTarget && MeNotInGroup && canCast, Me.CurrentTarget)) return true;

            //heals
            //if (await NeedHeals(true)) return true;
            return false;
        }
        #endregion

        #region power word solace
        public static bool needPowerWordSolace { get { return Me.ManaPercent <= P.myPrefs.PercentSolace && SpellManager.HasSpell(POWER_WORD_SOLACE); } }
        public static WoWUnit _solaceTarget
        {
            get
            {
                if (MeNotInGroup) { return Me.CurrentTarget != null ? Me.CurrentTarget : null; }
                var result = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p != null
                    && (p.Combat
                    && (p.IsTargetingMeOrPet || p.IsTargetingMyPartyMember || p.IsTargetingMyRaidMember))
                    && p.Distance <= 30
                    && Me.IsSafelyFacing(p)).OrderByDescending(p => p.HealthPercent).ToList();
                return result.Count() > 0 ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region binding heal
        public static int BindingHealHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentBindingHeal520;
                if (partyCount > 5 && partyCount <= 10) return P.myPrefs.percentBindingHeal510;
                return P.myPrefs.percentBindingHeal500;
            }
        }
        public static WoWUnit _bindingHealTarget
        {
            get
            {
                var result = newPartyMembers.Where(p => p != null && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && !p.IsMe
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).FirstOrDefault();
                return result != null ? result : null;
            }
        }
        #endregion

        #region urgent healing
        public static WoWUnit _urgentHealPlayer
        {
            get
            {
                var t = newPartyMembers.Where(p => p != null && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.Distance <= 40
                    && p.HealthPercent <= 35).FirstOrDefault();
                return t != null ? t : null;
            }
        }
        #endregion

        public static int lightWellHealth = 65;
        public static int cascadeHealth = 75;
        public static int holySanctuaryHealth = 80;

        #region power shield
        public static bool needPWS
        {
            get { return partyCount < 6; }
        }
        public static WoWUnit _tankPlayer
        {
            get
            {
                var t = Tanks().Where(p => p != null
                    && p.IsAlive
                    && p.Distance <= 40
                    && !buffExists(WEAKENED_SOUL_INT, p)
                    && !buffExists(PWS, p)).FirstOrDefault();
                return t != null ? t : null;
            }
        }
        #endregion

        #region circle of healing
        public static int circleHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentCircleOfHealing520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentCircleOfHealing510;
                return P.myPrefs.percentCircleOfHealing500;
            }
        }
        public static int circleHealthCount
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.CircleOfHealingPlayers520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.CircleOfHealingPlayers510;
                return P.myPrefs.CircleOfHealingPlayers500;
            }
        }
        public static WoWUnit _circlePlayer
        {
            get
            {
                if (MeNotInGroup) return null;
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= circleHealth
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result.Count() >= circleHealthCount ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region prayer of healing
        public static int prayerHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentPrayerOfHealing520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentPrayerOfHealing510;
                return P.myPrefs.percentPrayerOfHealing500;
            }
        }
        public static int prayerHealthCount
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.PrayerOfHealingPlayers520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.PrayerOfHealingPlayers510;
                return P.myPrefs.PrayerOfHealingPlayers500;
            }
        }
        public static WoWUnit _prayerPlayer
        {
            get
            {
                if (MeNotInGroup) return null;
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= prayerHealth
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result.Count() >= prayerHealthCount ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region divine hymn
        public static int divineHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentDivineHymn520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentDivineHymn510;
                return P.myPrefs.percentDivineHymn500;
            }
        }
        public static int divineHealthCount
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.DivineHymnPlayers520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.DivineHymnPlayers510;
                return P.myPrefs.DivineHymnPlayers500;
            }
        }
        public static WoWUnit _divinePlayer
        {
            get
            {
                if (MeNotInGroup) return null;
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= divineHealth
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result.Count() >= divineHealthCount ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region holy sanctuary
        public static WoWUnit _sanctuaryPlayer
        {
            get
            {
                if (MeNotInGroup) return null;
                if (!buffExists(CHACKRA_SANCTUARY, Me)) return null;
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= holySanctuaryHealth
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result.Count() >= 3 ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region holy lightwell
        public static WoWUnit _lightWellPlayer
        {
            get
            {
                if (MeNotInGroup) return null;
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= lightWellHealth
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result.Count() >= 3 ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region cascade
        public static WoWUnit _cascadePlayer
        {
            get
            {
                if (MeNotInGroup) return null;
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= cascadeHealth
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result.Count() >= 3 ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region mindbender
        public static bool needMindbender
        {
            get
            {
                if (!SpellManager.HasSpell(MINDBENDER)) return false;
                if (spellOnCooldown(MINDBENDER)) return false;
                if (partyCount > 10 && P.myPrefs.buttonMindbender500 && Me.ManaPercent <= P.myPrefs.percentManaMindbender500) return true;
                if ((partyCount > 5 && partyCount <= 10) && P.myPrefs.buttonMindbender500 && Me.ManaPercent <= P.myPrefs.percentManaMindbender500) return true;
                return P.myPrefs.buttonMindbender500 && Me.ManaPercent <= P.myPrefs.percentManaMindbender500;
            }
        }
        public static WoWUnit _mindbenderUnit
        {
            get
            {
                if (MeNotInGroup) return gotTarget && needMindbender ? Me.CurrentTarget : null;
                var result = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p != null
                    && (p.Combat
                    && (p.IsTargetingMeOrPet || p.IsTargetingMyPartyMember || p.IsTargetingMyRaidMember))
                    && p.InLineOfSight
                    && p.Distance <= 39).OrderByDescending(p => p.HealthPercent).ToList();
                return result.Count() > 0 ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region chakras
        public static bool needChakraSerenity
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.buttonChakraSernenity520;
                if (partyCount > 5 && partyCount <= 10) return P.myPrefs.buttonChakraSernenity510;
                return P.myPrefs.buttonChakraSernenity500;
            }
        }
        public static bool needChakraSanctuary
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.buttonChakraSanctuary520;
                if (partyCount > 5 && partyCount <= 10) return P.myPrefs.buttonChakraSanctuary510;
                return P.myPrefs.buttonChakraSanctuary500;
            }
        }
        #endregion

        #region partycount
        public static int partyCount
        {
            get
            {
                return Me.GroupInfo.NumRaidMembers == 0 ? Me.GroupInfo.NumPartyMembers : Me.GroupInfo.NumRaidMembers;
            }
        }
        #endregion


        #region disc

        public static WoWUnit _cascadeplayer = null;

        #region Power Word Shield
        public static WoWUnit _pwsPlayerDisc
        {
            get
            {
                if (MeNotInGroup && Me.HealthPercent <= 90 && !buffExists(WEAKENED_SOUL_INT, Me) && !buffExists(PWS, Me)) return Me;

                if (partyCount > 0)
                {
                    if (Tanks().Count() > 0)
                    {
                        var tanks = Tanks().Where(p => p != null
                            && p.IsAlive
                            && p.InLineOfSight
                            && p.Location.Distance(Me.Location) <= 40
                            && p.HealthPercent <= PD.myPrefs.PwsTanks
                            && !buffExists(PWS, p)
                            && !buffExists(WEAKENED_SOUL_INT, p)).OrderBy(p => p.HealthPercent).ToList();
                        return tanks != null ? tanks.FirstOrDefault() : null;
                    }

                    if (Healers().Count() > 0)
                    {
                        var healers = Healers().Where(p => p != null
                            && p.IsAlive
                            && p.InLineOfSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.PwsHealers
                            && !buffExists(PWS, p)
                            && !buffExists(WEAKENED_SOUL_INT, p)).OrderBy(p => p.HealthPercent).ToList();
                        return healers != null ? healers.FirstOrDefault() : null;
                    }

                    if (Damage().Count() > 0)
                    {
                        var damage = Damage().Where(p => p != null
                            && p.IsAlive
                            && p.InLineOfSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.PwsDamage
                            && !buffExists(PWS, p)
                            && !buffExists(WEAKENED_SOUL_INT, p)).OrderBy(p => p.HealthPercent).ToList();
                        return damage != null ? damage.FirstOrDefault() : null;
                    }
                }
                return null;
            }
        }
        #endregion

        #region Penance
        public static WoWUnit _penanceDiscPlayer
        {
            get
            {
                if (partyCount > 0)
                {
                    if (Tanks().Count() > 0)
                    {
                        var t = Tanks().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.PenanceTanks).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Healers().Count() > 0)
                    {
                        var t = Healers().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.PenanceHealers).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Damage().Count() > 0)
                    {
                        var t = Damage().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.PenanceDamage).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }
                }
                return null;
            }
        }
        #endregion

        #region smite
        public static bool CanCastSmite()
        {
            if (partyCount == 0) return false;
            if (!SpellManager.HasSpell(SMITE)) return false;
            if (PD.myPrefs.UseAtonement == 0) return false;
            if (PD.myPrefs.UseAtonement == 1 && Me.ManaPercent < PD.myPrefs.UseAtonementManaPercent) return false;
            if (dpsTarget == null) return false;
            return true;
        }
        #endregion

        #region holy fire
        public static bool CanCastHolyFire()
        {
            if (partyCount == 0) return false;
            if (!SpellManager.HasSpell(HOLY_FIRE)) return false;
            if (PD.myPrefs.UseAtonement == 0) return false;
            if (PD.myPrefs.UseAtonement == 1 && Me.ManaPercent < PD.myPrefs.UseAtonementManaPercent) return false;
            if (dpsTarget == null) return false;
            return true;
        }
        #endregion

        #region penance dps
        public static bool CanCastPenance()
        {
            if (partyCount == 0) return false;
            if (!SpellManager.HasSpell(PENANCE)) return false;
            if (PD.myPrefs.UseAtonement == 0) return false;
            if (PD.myPrefs.UseAtonement == 1 && Me.ManaPercent < PD.myPrefs.UseAtonementManaPercent) return false;
            if (PD.myPrefs.PenanceHealingOnly) return false;
            if (dpsTarget == null) return false;
            return true;
        }
        #endregion

        #region power word solace dps
        public static bool CanCastPowerWordSolace()
        {
            if (!SpellManager.HasSpell(POWER_WORD_SOLACE)) return false;
            if (spellOnCooldown(POWER_WORD_SOLACE)) return false;
            if (dpsTarget == null) return false;
            return true;
        }
        #endregion

        #region heal
        public static WoWUnit _healDiscPlayer
        {
            get
            {
                if (MeNotInGroup && Me.HealthPercent <= PD.myPrefs.HealTanks) return Me;
                if (partyCount > 0)
                {
                    if (Tanks().Count() > 0)
                    {
                        var t = Tanks().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.HealTanks).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Healers().Count() > 0)
                    {
                        var t = Healers().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.HealHealers).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Damage().Count() > 0)
                    {
                        var t = Damage().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.HealDamage).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }
                }
                return null;
            }
        }
        #endregion

        #region flashheal
        public static WoWUnit _flashHealDiscPlayer
        {
            get
            {
                if (MeNotInGroup && Me.HealthPercent <= PD.myPrefs.HealTanks) return Me;
                if (partyCount > 0)
                {
                    if (Tanks().Count() > 0)
                    {
                        var t = Tanks().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.FlashHealTanks).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Healers().Count() > 0)
                    {
                        var t = Healers().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.FlashHealHealers).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Damage().Count() > 0)
                    {
                        var t = Damage().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.FlashHealDamage).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }
                }
                return null;
            }
        }
        #endregion

        #region Prayer of Mending
        public static WoWUnit _prayerOfMendingDiscPlayer
        {
            get
            {
                if (partyCount > 0)
                {
                    if (Tanks().Count() > 0)
                    {
                        var t = Tanks().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.MendingTanks).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }

                    if (Healers().Count() > 0)
                    {
                        var t = Healers().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.MendingHealers).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }
                    if (Damage().Count() > 0)
                    {
                        var t = Damage().Where(p => p != null && p.IsAlive
                            && p.InLineOfSight
                            && p.InLineOfSpellSight
                            && p.Distance <= 40
                            && p.HealthPercent <= PD.myPrefs.MendingDamage).OrderBy(p => p.HealthPercent).ToList();
                        return t != null ? t.FirstOrDefault() : null;
                    }
                }
                return null;
            }
        }
        #endregion

        #region prayer of healing
        public static WoWUnit _prayerOfHealingPlayerDisc
        {
            get
            {
                if (!needPrayerOfHealing) return null;
                return healTarget;
            }
        }
        public static bool needPrayerOfHealing
        {
            get
            {
                if (partyCount == 0) return false;
                var result = newPartyMembers.Where(p => p != null && p.IsAlive && p.HealthPercent <= PD.myPrefs.PrayerOfHealingPercent).OrderBy(p => p.HealthPercent).ToList();
                if (result.Count() > 0) healTarget = result.FirstOrDefault();
                return result.Count() >= PD.myPrefs.PrayerOfHealingPlayerCount ? true : false;
            }
        }
        #endregion

        #region cascade
        public static bool needCascade()
        {
            var result = newPartyMembers.Where(p => p != null && p.IsAlive
                && p.Distance <= 40
                && p.InLineOfSight
                && p.HealthPercent <= PD.myPrefs.CascadeHealth).OrderBy(p => p.HealthPercent).ToList();
            if (result.Count() >= PD.myPrefs.CascadePlayerCount) { _cascadeplayer = result.FirstOrDefault(); }
            return _cascadeplayer != null ? true : false;

        }
        #endregion

        #region power word barrier
        public static WoWUnit _powerWordBarrierPlayerDisc
        {
            get
            {
                if (!needPowerWordBarrier) return null;
                return healTarget;
            }
        }
        public static bool needPowerWordBarrier
        {
            get
            {
                if (partyCount == 0) return false;
                if (!PD.myPrefs.BarrierAutoUse) return false;
                var result = newPartyMembers.Where(p => p != null && p.IsAlive && p.HealthPercent <= PD.myPrefs.BarrierPercent).OrderBy(p => p.HealthPercent).ToList();
                if (result.Count() > 0) healTarget = result.FirstOrDefault();
                return result.Count() >= PD.myPrefs.BarrierPlayerCount ? true : false;
            }
        }
        #endregion

        #region pain suppression
        public static WoWUnit _painsuppressionplayer = null;
        public static bool needPainSuppression
        {
            get
            {
                if (partyCount == 0) return false;
                if (partyCount > 0 && Tanks().Count() > 0)
                {
                    var t = Tanks().Where(p => p != null
                        && p.IsAlive
                        && p.HealthPercent <= PD.myPrefs.PainPercent
                        && p.Distance <= 40)
                        .OrderBy(p => p.HealthPercent)
                        .ToList();
                    if (t != null) _painsuppressionplayer = t.FirstOrDefault();
                    return t != null ? true : false;
                }
                return false;
            }
        }
        #endregion

        #region mindbender
        public static WoWUnit manaregenTarget = null;
        public static bool needManaRegen
        {
            get
            {
                if (!SpellManager.HasSpell(MINDBENDER)) return false;
                if (spellOnCooldown(MINDBENDER)) return false;
                if (partyCount == 0 && Me.ManaPercent <= PD.myPrefs.ManaRegenPercent && Me.CurrentTarget != null) return true;
                if (PD.myPrefs.ManaRegen == 2 && Me.ManaPercent > PD.myPrefs.ManaRegenPercent) return false;

                manaregenTarget = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p != null
                    && p.IsAlive
                    && (p.Combat
                    && (p.IsTargetingMeOrPet || p.IsTargetingMyPartyMember || p.IsTargetingMyRaidMember))
                    && p.InLineOfSight
                    && p.CanSelect
                    && Me.IsSafelyFacing(p)
                    && p.Location.Distance(Me.Location) <= 30).OrderByDescending(p => p.HealthPercent).FirstOrDefault();

                return manaregenTarget != null ? true : false;
            }
        }
        #endregion

        #region shadowfiend
        public static bool CanCastShadowFiend()
        {
            if (!SpellManager.HasSpell(SHADOWFIEND)) return false;
            if (spellOnCooldown(SHADOWFIEND)) return false;
            if (dpsTarget != null && dpsTarget.MaxHealth > Me.MaxHealth * 3) return true;
            return false;
        }
        #endregion

        #region holy nova
        public static bool needHolyNova
        {
            get
            {
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.Location.Distance(Me.Location) <= 12
                    && p.HealthPercent <= PD.myPrefs.HolyNovaPercent).ToList();
                return result.Count() >= PD.myPrefs.HolyNovaPlayerCount ? true : false;
            }
        }
        #endregion

        #region dps targets
        public static WoWUnit dpsTarget = null;

        public static bool canAttackTarget()
        {
            if (dpsTarget != null && IsAttackingTank()) return true;
            if (dpsTarget != null && IsAttackingDamage()) return true;
            return false;
        }

        public static bool IsAttackingTank()
        {
            if (attackTargets != null && Tanks().Count() > 0)
            {
                var target = Tanks().Where(p => p != null
                    && p.IsAlive
                    && p.CurrentTarget != null
                    && p.Combat
                    && attackTargets.Contains(p.CurrentTarget))
                    .Select(p => p.CurrentTarget)
                    .FirstOrDefault();
                if (target != null) dpsTarget = target;
                return target != null ? true : false;
            }
            return false;
        }
        public static bool IsAttackingDamage()
        {
            if (attackTargets != null && Damage().Count() > 0)
            {
                var target = Damage().Where(p => p != null
                    && p.IsAlive
                    && p.CurrentTarget != null
                    && p.Combat
                    && attackTargets.Contains(p.CurrentTarget))
                    .Select(p => p.CurrentTarget)
                    .FirstOrDefault();
                if (target != null) dpsTarget = target;
                return target != null ? true : false;
            }
            return false;
        }
        public static IEnumerable<WoWUnit> attackTargets
        {
            get
            {
                //WoWUnit targetToDps = null;
                List<WoWUnit> listT = new List<WoWUnit>();

                listT = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p != null
                    && p.Combat
                    && p.IsAlive
                    && p.InLineOfSight
                    && (p.CurrentTarget.IsTargetingMeOrPet || p.CurrentTarget.IsTargetingMyPartyMember || p.CurrentTarget.IsTargetingMyRaidMember)
                    && Me.IsSafelyFacing(p)
                    && p.CurrentTarget.Distance <= 30)
                    .OrderByDescending(p => p.HealthPercent)
                    .ToList();
                return listT.Count() > 0 ? listT : null;
            }
        }
        #endregion

        #endregion

        #region fill party
        public static IEnumerable<WoWUnit> getPartyMembers()
        {
            if (InProvingGrounds)
            {
                return Group.PulsePartyMembersPG().ToList();
            }
            else
            {
                List<WoWPlayer> list = new List<WoWPlayer>();
                list = StyxWoW.Me.GroupInfo.RaidMembers.Union(StyxWoW.Me.GroupInfo.PartyMembers)
                    .Select(p => p.ToPlayer()).Distinct().ToList();
                return list;
            }
        }
        public static IEnumerable<WoWUnit> newPartyMembers
        {
            get
            {
                return getPartyMembers();
            }
        }
        public static WoWUnit healTarget;
        public static WoWUnit aoeTarget;

        public static IEnumerable<WoWUnit> Tanks()
        {
            if (InProvingGrounds)
            {
                var tank = newPartyMembers.Where(p => p != null && p.Name == "Oto the Protector");
                return tank != null ? tank : null;
            }
            var result = StyxWoW.Me.GroupInfo.RaidMembers.Union(StyxWoW.Me.GroupInfo.PartyMembers)
                    .Where(p => p.HasRole(WoWPartyMember.GroupRole.Tank))
                        .Select(p => p.ToPlayer())
                        .ToList();
            return result.Count() > 0 ? result : null;
        }
        public static IEnumerable<WoWUnit> Healers()
        {
            var result = StyxWoW.Me.GroupInfo.RaidMembers.Union(StyxWoW.Me.GroupInfo.PartyMembers)
                    .Where(p => p.HasRole(WoWPartyMember.GroupRole.Healer))
                        .Select(p => p.ToPlayer())
                        .ToList();
            return result.Count() > 0 ? result : null;
        }
        public static IEnumerable<WoWUnit> Damage()
        {
            var result = StyxWoW.Me.GroupInfo.RaidMembers.Union(StyxWoW.Me.GroupInfo.PartyMembers)
                    .Where(p => p.HasRole(WoWPartyMember.GroupRole.Damage))
                        .Select(p => p.ToPlayer())
                        .ToList();
            return result.Count() > 0 ? result : null;
        }
        public static bool MeNotInGroup { get { return partyCount == 0; } }
        #endregion

        #region renew
        public static int renewHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentRenew520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentRenew510;
                return P.myPrefs.percentRenew500;
            }
        }
        public static bool needRenewOnTank
        {
            get
            {
                if (P.myPrefs.keepRenewOnTanks520 && partyCount > 10) return true;
                if (P.myPrefs.keepRenewOnTanks510 && (partyCount > 5 && partyCount <= 10)) return true;
                if (P.myPrefs.keepRenewOnTanks500 && partyCount <= 5) return true;
                return false;
            }
        }
        public static WoWUnit _tankRenewPlayer
        {
            get
            {
                if (InProvingGrounds)
                {
                    if (InProvingGrounds)
                    {
                        if (newPartyMembers.Count() > 0)
                        {
                            foreach (WoWUnit unit in newPartyMembers)
                            {
                                if (unit.Name == "Oto the Protector" && !buffExists(RENEW, unit)) return unit;
                            }
                        }
                        return null;
                    }
                }
                var result = Tanks().Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && !buffExists(RENEW, p)
                    && p.Distance <= 40);
                return result != null ? result.FirstOrDefault() : null;
            }
        }
        public static bool needRenew
        {
            get
            {
                if (MeNotInGroup && Me.HealthPercent <= renewHealth && !buffExists(RENEW, Me))
                {
                    SpellManager.Cast(RENEW, Me);
                    Logging.Write(Colors.Yellow, "Casting: " + RENEW + " on: " + Me.SafeName);
                    return false;
                }
                var result = newPartyMembers.Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= renewHealth
                    && !buffExists(RENEW, p)
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent);
                return result.Count() > 0 ? true : false;
            }
        }
        #endregion

        #region holy word serenity
        public static WoWUnit _serenityPlayer
        {
            get
            {
                if (MeNotInGroup) return buffExists(RENEW, Me) ? Me : null;
                var result = newPartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.InLineOfSpellSight
                        && buffExists(RENEW, p)
                        && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result != null ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region prayer of mending
        public static bool needFreePrayerOfMending
        {
            get { return IsOverlayed(PRAYER_OF_MENDING_INT); }
        }
        public static WoWUnit _freePrayerTarget
        {
            get
            {
                if (partyCount == 0) return Me;
                var result1 = Tanks().Where(p => p != null && p.IsAlive && p.InLineOfSpellSight && p.InLineOfSight && p.Distance <= 40).FirstOrDefault();
                if (result1 != null) return result1;
                var result2 = newPartyMembers.Where(p => p != null && p.IsAlive && p.InLineOfSpellSight && p.InLineOfSight && p.Distance <= 40).OrderBy(p => p.HealthPercent).FirstOrDefault();
                return result2 != null ? result2 : null;
            }
        }
        public static int prayerOfMendingHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentPrayerOfMending520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentPrayerOfMending510;
                return P.myPrefs.percentPrayerOfMending500;
            }
        }
        public static WoWUnit _prayerMendingPlayer
        {
            get
            {
                if (MeNotInGroup) return Me.HealthPercent <= prayerOfMendingHealth ? Me : null;
                var result = newPartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.InLineOfSpellSight
                        && p.HealthPercent <= prayerOfMendingHealth
                        && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result != null ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region Heal

        public static int healHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentHeal520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentHeal510;
                return P.myPrefs.percentHeal500;
            }
        }
        public static WoWUnit _healPlayer
        {
            get
            {
                if (MeNotInGroup) return Me.HealthPercent <= healHealth ? Me : null;
                var result = newPartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.InLineOfSpellSight
                        && p.HealthPercent <= healHealth
                        && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result != null ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region flash heal
        public static int flashHealth
        {
            get
            {
                if (partyCount > 10) return P.myPrefs.percentFlashHeal520;
                if (partyCount > 5 && partyCount < 10) return P.myPrefs.percentFlashHeal510;
                return P.myPrefs.percentFlashHeal500;
            }
        }
        public static WoWUnit _flashHealPlayer
        {
            get
            {
                if (MeNotInGroup) return Me.HealthPercent <= flashHealth ? Me : null;
                var result = newPartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.InLineOfSpellSight
                        && p.HealthPercent <= flashHealth
                        && p.Distance <= 40).OrderBy(p => p.HealthPercent).ToList();
                return result != null ? result.FirstOrDefault() : null;
            }
        }
        #endregion

        #region GuardianSpirit
        public static WoWUnit _guardianSpiritPlayer
        {
            get
            {
                if (InProvingGrounds)
                {
                    if (newPartyMembers.Count() > 0)
                    {
                        foreach (WoWUnit unit in newPartyMembers)
                        {
                            if (unit.Name == "Oto the Protector" && unit.HealthPercent <= P.myPrefs.percentGuardianSpiritTank) return unit;
                        }
                    }
                    return null;
                }
                return Tanks().Where(p => p != null
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= P.myPrefs.percentGuardianSpiritTank
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent).FirstOrDefault();
            }
        }
        #endregion

        #region dispel
        public static WoWUnit dispelTargets
        {
            get
            {
                if (!P.myPrefs.AutoDispel) return null;
                WoWUnit dispelTarget = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p != null
                    && p.Combat
                    && (p.IsTargetingMeOrPet || p.IsTargetingMyPartyMember || p.IsTargetingMyRaidMember)
                    && CanDispelMagic(p)
                    && p.Distance <= 30).OrderBy(p => p.Distance).FirstOrDefault();
                return dispelTarget != null ? dispelTarget : null;
            }
        }
        #endregion

        #region purify
        public static WoWUnit purifyPlayers
        {
            get
            {
                if (!P.myPrefs.AutoDispel) return null;
                WoWPlayer purifyTarget = ObjectManager.GetObjectsOfTypeFast<WoWPlayer>()
                    .Where(p => p != null
                        && (p.IsInMyPartyOrRaid || p.IsMe)
                        && p.IsAlive
                        && CanPurifyTarget(p)).FirstOrDefault();
                return purifyTarget != null ? purifyTarget : null;
            }
        }
        #endregion

        #region canCast
        public static bool canCast
        {
            get { return !Me.IsCasting && !Me.IsChanneling; }
        }
        #endregion

        #region proving grounds
        public static bool InProvingGrounds { get { return Me.MinimapZoneText == "Proving Grounds"; } }
        #endregion

        #region healing spellcasts
        public static async Task<bool> CastMultiDot(string spell, bool reqs)
        {
            if (!reqs) return false;
            Logging.Write(Colors.Yellow, "MultiDot Renew");

            var result = newPartyMembers.Where(p => p != null
                    && Group.IsValidObject(p)
                    && p.IsAlive
                    && p.InLineOfSight
                    && p.InLineOfSpellSight
                    && p.HealthPercent <= renewHealth
                    && !buffExists(RENEW, p)
                    && p.Distance <= 40).OrderBy(p => p.HealthPercent);
            if (result.Count() > 0)
            {
                foreach (WoWUnit unit in result)
                {
                    if (canCast
                        && SpellManager.CanCast(RENEW))
                    {
                        SpellManager.Cast(RENEW, unit);
                        await CommonCoroutines.SleepForLagDuration();
                    }
                }
            }
            await CommonCoroutines.SleepForLagDuration();
            return true;
        }
        public static async Task<bool> CastHeal(string Spell, bool reqs, WoWUnit myTarget)
        {
            if (!SpellManager.HasSpell(Spell)) return false;
            if (!reqs) return false;
            if (spellOnCooldown(Spell)) return false;
            if (!SpellManager.CanCast(Spell, myTarget)) return false;
            if (!SpellManager.Cast(Spell, myTarget)) return false;
            Logging.Write(Colors.Yellow, "Casting: " + Spell + " on: " + myTarget.SafeName);
            await CommonCoroutines.SleepForLagDuration();
            return true;
        }
        public static async Task<bool> CastNonTargetSpell(string Spell, bool reqs)
        {
            if (!SpellManager.HasSpell(Spell)) return false;
            if (!reqs) return false;
            if (spellOnCooldown(Spell)) return false;
            if (!SpellManager.CanCast(Spell)) return false;
            if (!SpellManager.Cast(Spell)) return false;
            Logging.Write(Colors.Yellow, "Casting: " + Spell);
            await CommonCoroutines.SleepForLagDuration();
            return true;
        }
        public static async Task<bool> CastDmgSpell(string Spell, bool reqs, WoWUnit myTarget)
        {
            if (!SpellManager.HasSpell(Spell)) return false;
            if (!reqs) return false;
            if (spellOnCooldown(Spell)) return false;
            if (!SpellManager.CanCast(Spell, myTarget)) return false;
            if (!SpellManager.Cast(Spell, myTarget)) return false;
            Logging.Write(Colors.Yellow, "Casting: " + Spell + " on: " + myTarget.SafeName);
            await CommonCoroutines.SleepForLagDuration();
            return true;
        }
        private static async Task<bool> CastGroundSpell(string spell, bool reqs, WoWUnit target)
        {
            if (!reqs) return false;
            if (!SpellManager.HasSpell(spell)) return false;
            if (spellOnCooldown(spell)) return false;
            if (!SpellManager.CanCast(spell))
                return false;
            if (!SpellManager.Cast(spell))
                return false;
            if (!await Coroutine.Wait(1000, () => StyxWoW.Me.CurrentPendingCursorSpell != null))
            {
                Logging.WriteDiagnostic("Cursor didn't turn into the spell!");
                return false;
            }
            SpellManager.ClickRemoteLocation(target.Location);
            await CommonCoroutines.SleepForLagDuration();
            return true;
        }
        #endregion

    }
}